package edu.unice.simul.modele.contenus.mobiles;

import edu.unice.simul.util.Dim;
import edu.unice.simul.util.DimDouble;

/**
 * Cette classe encapsule les attributs des humains afin de rendre plus lisible
 * la classe Humain.
 * 
 * @author Romain Ciaccafava
 * 
 */
public class EtatHumain {
	/**
	 * L'agressivité doit être comprise entre 0.5 et 2.0.
	 */
	private double agressivite = 1.7;
	/**
	 * Angle de vision (en radians). Il doit être compris entre pi/4 et pi/2.
	 */
	private double angleVision = 1.0;
	/**
	 * La courtoisie correspond à la distance que respectent les humains entre
	 * eux. Commence à 3 (environ 1 m).
	 */
	private double courtoisie = 3.0;
	/**
	 * Masse de l'humain
	 */
	private int masse = 70;
	/**
	 * Vitasse maximale que peut atteindre l'humain en km/h. Cette vitesse dépend
	 * notamment de l'âge. (maximum = 8)
	 */
	private int vitesseMax = 8;
	/**
	 * Pourcentage de vie de l'humain (0 = mort; 100 = en pleine forme)
	 */
	private double prcVie = 100.;
	/**
	 * Pourcentage de stress de l'humain
	 */
	private double prcStress = 0.0;
	/**
	 * Décision prise par l'humain. Module et direction de la vitesse souhaitée.
	 */
	private double vitesseSouhaitee;
	private double directionSouhaitee;
	/**
	 * Forces de contact subie par l'humain
	 */
	private double forceContactX, forceContactY;

	// Optimisation
	private double deltaT = 0.03;
	private double dtSurTau;
	private double dt2SurTau;
	private double dt2SurM;

	/**
	 * Défini sur l'humain est sorti de la pièce
	 */
	private boolean sorti = false;
	/**
	 * Temps de sortie de l'humain, le cas échéant
	 */
	private double tempsDeSortie;
	/**
	 * Porte de sortie utilisée par l'humain, le cas échéant
	 */
	private Dim porteDeSortie = null;

	private DimDouble coordonneeReele = new DimDouble();
	private DimDouble ancienneCoordonneeReele = new DimDouble();

	public EtatHumain() {
	}

	/**
	 * Constructeur par copie qui pourra être utile si on décide de stocker l'état
	 * précédent de l'humain.
	 */
	public EtatHumain(EtatHumain etat) {
		this.agressivite = etat.agressivite;
		this.ancienneCoordonneeReele = etat.ancienneCoordonneeReele;
		this.angleVision = etat.angleVision;
		this.coordonneeReele = etat.coordonneeReele;
		this.courtoisie = etat.courtoisie;
		this.directionSouhaitee = etat.directionSouhaitee;
		this.forceContactX = etat.forceContactX;
		this.forceContactY = etat.forceContactY;
		this.masse = etat.masse;
		this.prcVie = etat.prcVie;
		this.deltaT = etat.deltaT;
		this.dtSurTau = this.deltaT * this.agressivite;
		this.dt2SurTau = this.deltaT * this.dtSurTau;
		this.dt2SurM = this.deltaT * this.deltaT / this.masse;
	}

	public double getVitesseSouhaitee() {
		return vitesseSouhaitee;
	}

	public void setVitesseSouhaitee(double vitesseSouhaitee) {
		this.vitesseSouhaitee = vitesseSouhaitee;
	}

	public double getDirectionSouhaitee() {
		return directionSouhaitee;
	}

	public void setDirectionSouhaitee(double directionSouhaitee) {
		this.directionSouhaitee = directionSouhaitee;
	}

	public double getForceContactX() {
		return forceContactX;
	}

	public void setForceContactX(double forceContactX) {
		this.forceContactX = forceContactX;
	}

	public double getForceContactY() {
		return forceContactY;
	}

	public void setForceContactY(double forceContactY) {
		this.forceContactY = forceContactY;
	}

	public boolean estSorti() {
		return sorti;
	}

	public double getTempsDeSortie() {
		return tempsDeSortie;
	}

	public Dim getPorteDeSortie() {
		return porteDeSortie;
	}

	public double getAgressivite() {
		return agressivite;
	}

	public void setAgressivite(double agressivite) {
		if (agressivite > 0.49 && agressivite < 2.01) {
			this.agressivite = agressivite;
			this.dtSurTau = this.deltaT * agressivite;
			this.dt2SurTau = this.dtSurTau * this.deltaT;
		} else {
		}
	}

	public double getAngleVision() {
		return angleVision;
	}

	public void setAngleVision(double angleVision) {
		this.angleVision = angleVision;
	}

	public double getCourtoisie() {
		return courtoisie;
	}

	public int getMasse() {
		return masse;
	}

	public void setVitesseMax(int vitesseMax) {
		if (vitesseMax > 0 && vitesseMax < 9)
			this.vitesseMax = vitesseMax;
	}

	public int getVitesseMax() {
		return vitesseMax;
	}

	public void setMasse(int masse) {
		if (masse > 20 && masse < 200) {
			this.masse = masse;
			this.dt2SurM = this.deltaT * this.deltaT / masse;
		}
	}

	public double getPrcVie() {
		return prcVie;
	}

	public void setPrcVie(double prcVie) {
		this.prcVie = prcVie;
	}

	public void setSorti(double temps, Dim porteDeSortie) {
		this.sorti = true;
		this.tempsDeSortie = temps;
		this.porteDeSortie = porteDeSortie;
	}

	/**
	 * Diminue la vie de l'humain.
	 * 
	 * @param prc
	 *          pourcentage de vie à enlever
	 */
	public void diminuerVie(double prc) {
		this.prcVie -= prc;
		if (this.prcVie < 0 || this.prcVie > 100)
			this.prcVie = 0;
	}

	public void augmenterStress(double prc) {
		this.prcStress += prc;
		if (this.prcStress < 0 || this.prcStress > 100)
			this.prcStress = 100;
	}

	@Override
	public String toString() {
		return "EtatHumain [agressivite=" + agressivite + ", angleVision="
				+ angleVision + ", courtoisie=" + courtoisie + ", masse=" + masse
				+ ", vitesseMax=" + vitesseMax + ", prcVie=" + prcVie + ", prcStress="
				+ prcStress + ", vitesseSouhaitee=" + vitesseSouhaitee
				+ ", directionSouhaitee=" + directionSouhaitee + ", forceContactX="
				+ forceContactX + ", forceContactY=" + forceContactY + ", deltaT="
				+ deltaT + ", dtSurTau=" + dtSurTau + ", dt2SurTau=" + dt2SurTau
				+ ", dt2SurM=" + dt2SurM + ", sorti=" + sorti + ", tempsDeSortie="
				+ tempsDeSortie + ", porteDeSortie=" + porteDeSortie
				+ ", coordonneeReele=" + coordonneeReele + ", ancienneCoordonneeReele="
				+ ancienneCoordonneeReele + "]";
	}

	public DimDouble getCoordonneeReele() {
		return coordonneeReele;
	}

	public DimDouble getAncienneCoordonneeReele() {
		return ancienneCoordonneeReele;
	}

	public double getPrcStress() {
		return prcStress;
	}

	public void setPrcStress(double prcStress) {
		this.prcStress = prcStress;
	}

	public double getDtSurTau() {
		return dtSurTau;
	}

	public void setDtSurTau(double dtSurTau) {
		this.dtSurTau = dtSurTau;
	}

	public double getDt2SurTau() {
		return dt2SurTau;
	}

	public void setDt2SurTau(double dt2SurTau) {
		this.dt2SurTau = dt2SurTau;
	}

	public double getDt2SurM() {
		return dt2SurM;
	}

	public void setDt2SurM(double dt2SurM) {
		this.dt2SurM = dt2SurM;
	}

	public double getDeltaT() {
		return deltaT;
	}
}
